#include <activity.h>
#include <types.h>
#include <subprograms.h>
#include <deployment.h>
#include <csra.h>
#include <po_hi_task.h>
#include <po_hi_types.h>
#include <po_hi_main.h>
#include <po_hi_messages.h>
#include <ssra.h>
#include <marshallers.h>
#include <po_hi_protocols.h>
#include <po_hi_gqueue.h>

#include <stdio.h>
/*  Periodic task : Pinger*/
/****************/
/* pinger_job */ 
/****************/

extern __po_hi_entity_t __po_hi_port_global_to_entity[__PO_HI_NB_PORTS];
extern __po_hi_entity_t __po_hi_port_global_to_local_port[__PO_HI_NB_PORTS];

void main_deliver(__po_hi_msg_t* msg)
{
        __po_hi_request_t request;
        __po_hi_entity_t entity;
        __po_hi_unmarshall_generic(&request,msg);
        entity = __po_hi_port_global_to_entity[request.port];
        switch (entity)
        {
                case node_a_ping_me_k_entity:
                        {
                                ping_me_deliver(&request);
                                break;
                        }
                default:
                        break;
        }
}

__po_hi_port_t __po_hi_pinger_history[__PO_HI_PINGER_NB_PORTS];
__po_hi_uint8_t __po_hi_pinger_woffsets[__PO_HI_PINGER_NB_PORTS];
__po_hi_uint8_t __po_hi_pinger_empties[__PO_HI_PINGER_NB_PORTS];
__po_hi_uint8_t __po_hi_pinger_first[__PO_HI_PINGER_NB_PORTS];
__po_hi_uint8_t __po_hi_pinger_queue[0 * sizeof (__po_hi_request_t)];
__po_hi_uint8_t __po_hi_pinger_recent[__PO_HI_PINGER_NB_PORTS * sizeof (__po_hi_request_t)];

__po_hi_int8_t __po_hi_pinger_fifo_sizes[__PO_HI_PINGER_NB_PORTS] = {-2};
__po_hi_uint8_t __po_hi_pinger_offsets[__PO_HI_PINGER_NB_PORTS] = {0};
__po_hi_uint8_t __po_hi_pinger_used_size[__PO_HI_PINGER_NB_PORTS];
__po_hi_uint8_t __po_hi_pinger_n_destinations[__PO_HI_PINGER_NB_PORTS] = {1};
__po_hi_uint8_t pinger_data_source_destinations[1] = {data_sink};
__po_hi_uint8_t* __po_hi_pinger_destinations[__PO_HI_PINGER_NB_PORTS] = {pinger_data_source_destinations};
__po_hi_uint16_t __po_hi_pinger_total_fifo_size = 0;



void* pinger_job ()
{
   simple_type p_spg_data_source;
   __po_hi_request_t request;
   __po_hi_gqueue_init (node_a_pinger_k, 
                        __PO_HI_PINGER_NB_PORTS,
                        __po_hi_pinger_queue,
                        __po_hi_pinger_fifo_sizes,
                        __po_hi_pinger_first,
                        __po_hi_pinger_offsets, 
                        __po_hi_pinger_woffsets, 
                        __po_hi_pinger_n_destinations, 
                        __po_hi_pinger_destinations,
                        __po_hi_pinger_used_size,
                        __po_hi_pinger_history,
                        __po_hi_pinger_recent,
                        __po_hi_pinger_empties,
                        __po_hi_pinger_total_fifo_size);
   __po_hi_wait_initialization();
   while (1)
   {
      /*  Call implementation*/
      do_ping_spg(&(p_spg_data_source));
      request.port = data_source;
      request.vars.data_source.data_source = p_spg_data_source;
      __po_hi_gqueue_store_out (node_a_pinger_k, pinger_data_source, &request);
      /*  Call stub */
      __po_hi_gqueue_send_output (node_a_pinger_k, data_source);
      __po_hi_wait_for_next_period(node_a_pinger_k);
   }
}


/*  Sporadic task : Ping_Me*/
/*****************/
/* ping_me_job */ 
/*****************/

__po_hi_port_t __po_hi_pingme_history[__PO_HI_PINGME_NB_PORTS];
__po_hi_uint8_t __po_hi_pingme_woffsets[__PO_HI_PINGME_NB_PORTS];
__po_hi_uint8_t __po_hi_pingme_empties[__PO_HI_PINGME_NB_PORTS];
__po_hi_uint8_t __po_hi_pingme_first[__PO_HI_PINGME_NB_PORTS];
__po_hi_uint8_t __po_hi_pingme_queue[16 * sizeof (__po_hi_request_t)];
__po_hi_uint8_t __po_hi_pingme_recent[__PO_HI_PINGME_NB_PORTS * sizeof (__po_hi_request_t)];
__po_hi_int8_t __po_hi_pingme_fifo_sizes[__PO_HI_PINGME_NB_PORTS] = {16};
__po_hi_uint8_t __po_hi_pingme_offsets[__PO_HI_PINGME_NB_PORTS] = {1};
__po_hi_uint8_t __po_hi_pingme_n_destinations[__PO_HI_PINGME_NB_PORTS] = {0};
__po_hi_uint8_t __po_hi_pingme_used_size[__PO_HI_PINGME_NB_PORTS];
__po_hi_uint8_t* __po_hi_pingme_destinations[__PO_HI_PINGME_NB_PORTS] = {NULL};
__po_hi_uint16_t __po_hi_pingme_total_fifo_size = 16;

void ping_me_deliver(__po_hi_request_t* request)
{
        switch (request->port)
        {
                case data_sink:
                        {
                                __po_hi_gqueue_store_in (node_a_ping_me_k, pingme_data_sink, request);
                                break;
                        }
                default:
                        {
                                fprintf(stderr,"ERROR IN SWITH IN ping_me_deliver\n");
                        }
        }
}

void* ping_me_job ()
{
   __po_hi_msg_t message;
   __po_hi_port_t port;
   __po_hi_request_t request;

   __po_hi_gqueue_init (node_a_ping_me_k, 
                     __PO_HI_PINGME_NB_PORTS,
                     __po_hi_pingme_queue,
                     __po_hi_pingme_fifo_sizes,
                     __po_hi_pingme_first,
                     __po_hi_pingme_offsets, 
                     __po_hi_pingme_woffsets, 
                     __po_hi_pingme_n_destinations, 
                     __po_hi_pingme_destinations,
                     __po_hi_pingme_used_size,
                     __po_hi_pingme_history,
                     __po_hi_pingme_recent,
                     __po_hi_pingme_empties,
                     __po_hi_pingme_total_fifo_size);
   __po_hi_wait_initialization();
   while (1)
   {
           __po_hi_gqueue_wait_for_incoming_event (node_a_ping_me_k, &port);
           __po_hi_compute_next_period (node_a_ping_me_k);
           if (__po_hi_gqueue_get_count(node_a_ping_me_k, pingme_data_sink) != -1)
           {
                   __po_hi_gqueue_get_value(node_a_ping_me_k,pingme_data_sink,&request);
                   __po_hi_gqueue_next_value(node_a_ping_me_k,pingme_data_sink);
           }
           ping_spg(request.vars.data_sink.data_sink);
           __po_hi_msg_reallocate(&(message));
           __po_hi_wait_for_next_period (node_a_ping_me_k);
   }
}


